#include <interrupts.h>
#include <cpu.h>
#include <stddef.h>
#include <spinlock.h>

spinlock_t irq_lock = SPINLOCK_INITVAL;
irq_handler_t irq_handlers[IRQ_NUM]; 

static void irq_set_handler(unsigned id, irq_handler_t handler){
    if(id < IRQ_NUM)
        irq_handlers[id] = handler;
}

static void irq_enable(unsigned id)
{
    return arch_irq_enable(id);
}

static void irq_disable(unsigned id)
{
    arch_irq_disable(id);
}

static void irq_set_prio(unsigned id, unsigned prio)
{
    arch_irq_set_prio(id, prio);
}

void interrupts_cpu_sendipi(uint64_t target_cpu, uint64_t ipi_id)
{
    arch_irq_send_ipi(target_cpu, ipi_id);
}

void request_irq(unsigned id, irq_handler_t handler)
{
    spin_lock(&irq_lock);
    irq_set_handler(id, handler);
    irq_enable(id);
    irq_set_prio(id, IRQ_MAX_PRIO);
    spin_unlock(&irq_lock);
}

void free_irq(unsigned id)
{
    irq_disable(id);
}

void irq_handle(unsigned id){
    if(id < IRQ_NUM && irq_handlers[id] != NULL)
        irq_handlers[id](id);
}

void interrupts_init(void)
{
    arch_interrupts_init();

    if(cpu_is_master()){
        /* 用SGI 0号中断来做cpu间通信 */
        request_irq(IPI_CPU_MSG, cpu_msg_handler);
    }

    /* SGI是per-cpu的，故每个cpu自己都要unmask中断 */
    irq_enable(IPI_CPU_MSG);
    irq_set_prio(IPI_CPU_MSG, IRQ_MAX_PRIO);
}

